<?php
/**
 * Created by PhpStorm.
 * User: ship
 * Date: 2024/12/25
 * Time: 19:03
 */

namespace ShipSun\LaravelSignature;

use Illuminate\Support\Str;

/**
 * Class SigningStr
 * @package ShipSun\LaravelSignature
 */
class SigningStr
{
    /**
     * @var array
     */
    protected $param;

    /**
     * SigningStr constructor.
     * @param array $param
     */
    public function __construct(array $param)
    {
        $this->param = $param;
    }

    protected function checkParam(array $data)
    {
        foreach ($this->param as $value) {
            if ($this->isMethod($value)) {
                continue;
            }
            if (!isset($data[$value])) {
                throw new Exception(Exception::CHECK_PARAM_FAIL, ['key' => $value]);
            }
        }
    }

    /**
     * 是否拼接字段
     * @param string $key
     * @return bool
     */
    protected function isMethod(string $key)
    {
        $one = substr($key, 0, 1);
        if ($one == '@') {
            return true;
        }
        return false;
    }

    /**
     * @param string $key
     * @return string
     */
    protected function getMethodName(string $key)
    {
        $key = substr($key, 1);
        return Str::camel($key);
    }

    /**
     * @param $data
     * @return string
     */
    protected function requestTarget($data)
    {
        return strtolower($data['method']) . ' /' . trim($data['request_uri'], '/');
    }

    /**
     * @param $data
     * @return string
     */
    protected function mergeStr($data)
    {
        $str = '';
        foreach ($this->param as $key) {
            if ($this->isMethod($key)) {
                $method = $this->getMethodName($key);
                $str .= $key . ": " . call_user_func([$this, $method], $data);
            } else {
                $str .= $key . ": " . $data[$key];
            }
            $str .= "\n";
        }
        return rtrim($str, "\n");
    }

    /**
     * @param $data
     * @return string
     */
    public function create($data)
    {
        $this->checkParam($data);
        return $this->mergeStr($data);
    }
}